#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "hardware/adc.h"
#include "pico/multicore.h"
#include "pico/util/queue.h"
#include "dht.h"
#include "fan.h"
#include "ssd1306.h"


// DHT11 温度传感器
const int DHT_PIN = 8;
// NAS主板区风扇控制
const int B_FAN_CONTROL_PIN = 12;
// NAS主板区风扇转速获取
const int B_FAN_SPEED_PIN = 10;

// NAS存储区风扇控制
const int FAN_CONTROL_PIN = 13;
// NAS存储区风扇转速获取
const int FAN_SPEED_PIN = 11;

// IIC显示屏
const int SSD1306_SDA_PIN = 18;
const int SSD1306_SCL_PIN = 19;

// ADC输入号
const int ADC_INPUT = 3;

// 队列和长度
queue_t mq;
const uint mq_count = 5;

// 用来存储温湿度和转速的结构体
typedef struct {
    float adc_temperature_c;     // 主板区温度
    float temperature_c;		 // 存储区温度
	float humidity;			     // 主板区湿度
	float fanspeed;				 // 存储区风扇转速
	float b_fanspeed;			 // 主板区风扇转速
} TransData;


// 通过PICO集成的ADC传感器获取温度
float get_adc_temperature()
{
    float voltage = 0.0;
	float temp = 0.0;
	// 最大电压值3.3V, 12位转换精度
	voltage = adc_read() * 3.3f / (1 << 12);
	temp = 27 - (voltage - 0.706) / 0.001721;
	return temp;
}

void core1_entry()
{
    // 用来存放最终数据的变量
	TransData td;
	
    // dht11传感器初始化
    dht_t dht;
    dht_init(&dht, DHT11, pio0, DHT_PIN, true /* pull_up */);
    
	// 获取风扇转速引脚初始化
	gpio_init(FAN_SPEED_PIN);    // 存储区
	gpio_init(B_FAN_SPEED_PIN);  // 主板区
	gpio_set_dir(FAN_SPEED_PIN, GPIO_IN);   // 存储区
	gpio_set_dir(B_FAN_SPEED_PIN, GPIO_IN); // 主板区
	gpio_pull_up(FAN_SPEED_PIN); 	// 存储区风扇转速GPIO上拉				
	gpio_pull_up(B_FAN_SPEED_PIN);  // 主板区风扇转速GPIO上拉
    
	// 初始化ADC
	adc_init();
	adc_set_temp_sensor_enabled(true);
	adc_select_input(ADC_INPUT);

	while(1)
	{
	    // 获取温湿度
	    float humidity;
		float temperature_c;
		float adc_temperature_c;
		
		// 主板区温度获取
		td.adc_temperature_c = get_adc_temperature();

		// 存储区温湿度获取
        dht_start_measurement(&dht);
        dht_result_t result = dht_finish_measurement_blocking(&dht, &humidity, &temperature_c);
        if (result == DHT_RESULT_OK) 
		{
            // printf("%.1f C (%.1f F), %.1f%% humidity\n", temperature_c, celsius_to_fahrenheit(temperature_c), humidity);
			td.temperature_c = temperature_c;
			td.humidity = humidity;
        } 
		else if (result == DHT_RESULT_TIMEOUT) 
		{
            puts("DHT sensor not responding. Please check your wiring.");
        } else 
		{
            assert(result == DHT_RESULT_BAD_CHECKSUM);
            puts("Bad checksum");
        }

        // 获取存储区风扇当前转速
		float speed = 0.0;
        get_fan_speed(FAN_SPEED_PIN, &speed);
        if(speed)
		{
            td.fanspeed = speed;
		}
		else
		{
			td.fanspeed = 0.0;
		}

		// 获取主板区风扇转速
		float b_speed = 0.0;
		get_fan_speed(B_FAN_SPEED_PIN, &b_speed);
        if(b_speed)
		{
            td.b_fanspeed = b_speed;
		}
		else
		{
			td.b_fanspeed = 0.0;
		}
		



        // 将数据推入队列
        queue_try_add(&mq, &td);
	    sleep_ms(2000);
	}

}

void main()
{
    stdio_init_all();
    
	// 初始化队列
	queue_init(&mq, sizeof(TransData), mq_count);

    // core1负责获取温湿度和风扇的速度
	multicore_launch_core1(core1_entry);
    
	// 控制风扇转速引脚初始化
	gpio_init(FAN_CONTROL_PIN);
	gpio_init(B_FAN_CONTROL_PIN);
    gpio_set_function(FAN_CONTROL_PIN, GPIO_FUNC_PWM);
    gpio_set_function(B_FAN_CONTROL_PIN, GPIO_FUNC_PWM);
    
	// OLED显示屏初始化
	i2c_init(i2c1, 400000);
    gpio_set_function(SSD1306_SDA_PIN, GPIO_FUNC_I2C);
	gpio_set_function(SSD1306_SCL_PIN, GPIO_FUNC_I2C);
	gpio_pull_up(SSD1306_SDA_PIN);
	gpio_pull_up(SSD1306_SCL_PIN);
	ssd1306_t disp;
	disp.external_vcc = false;
	ssd1306_init(&disp, 128, 32, 0x3C, i2c1);
	ssd1306_clear(&disp);
     
    // core0负责控制风扇的转速和打印信心
    while(1)
    {  
	    // 从队列中拿数据
	    TransData td;
        queue_try_remove(&mq, &td);
		printf("Temp is %.2f, Humi is %.2f%%, Fan Speed is %.2f \n", td.temperature_c, td.humidity, td.fanspeed);
        // 将数据输出到OLED
		char temp[50] = "\0";
		char adc_temp[50] = "\0";
		char humi[50] = "\0";
		char speed[50] = "\0";
		char b_speed[50] = "\0";

		sprintf(temp, "Temperature: %.2f", td.temperature_c);
		sprintf(adc_temp, "Temperature: %.2f", td.adc_temperature_c);
		sprintf(humi, "Humidity: %.2f%%", td.humidity);
		sprintf(speed, "FanSpeed: %.2f", td.fanspeed);
		sprintf(b_speed, "FanSpeed: %.2f", td.b_fanspeed);

		// 显示主板区信息
		char *board_title = ">>Board Area<<";
		ssd1306_clear(&disp);
		ssd1306_draw_string(&disp, 0, 0, 1, board_title);
		ssd1306_draw_string(&disp, 0, 8, 1, adc_temp);
		ssd1306_draw_string(&disp, 0, 16, 1, b_speed);
		ssd1306_show(&disp);
        sleep_ms(2000);
		
		// 显示存储区信息
		char *storage_title = ">>Storage Area<<";
		ssd1306_clear(&disp);
		ssd1306_draw_string(&disp, 0, 0, 1, storage_title);
		ssd1306_draw_string(&disp, 0, 8, 1, temp);
		ssd1306_draw_string(&disp, 0, 16, 1, humi);
		ssd1306_draw_string(&disp, 0, 24, 1, speed);
		ssd1306_show(&disp);
        sleep_ms(2000);

           
		/* 存储区风扇转速控制
		 * T 为温度值
		 * T < 25 : level1
		 * 25 <= T < 35 :levle2
		 * 35 <= T < 45 :level3
		 * 45 <= T < 55 :level4
		 */
		if(td.temperature_c < 25.0)
		{
            fan_control(FAN_CONTROL_PIN, FAN_SPEED_LEVEL1);
		}
        else if(td.temperature_c >= 25.00 && td.temperature_c < 35.00)
		{
            fan_control(FAN_CONTROL_PIN, FAN_SPEED_LEVEL2);
		}
        else if(td.temperature_c >= 35.00 && td.temperature_c < 45.00)
		{
            fan_control(FAN_CONTROL_PIN, FAN_SPEED_LEVEL3);
		}
		else if(td.temperature_c >= 45.00)
		{
            fan_control(FAN_CONTROL_PIN, FAN_SPEED_LEVEL4);
		}


		/* 主板区风扇转速控制
		 * T 为温度值
		 * T < 25 : level1
		 * 25 <= T < 35 :levle2
		 * 35 <= T < 45 :level3
		 * 45 <= T < 55 :level4
		 */
		if(td.adc_temperature_c < 25.0)
		{
            fan_control(B_FAN_CONTROL_PIN, FAN_SPEED_LEVEL1);
		}
        else if(td.adc_temperature_c >= 25.00 && td.adc_temperature_c < 35.00)
		{
            fan_control(B_FAN_CONTROL_PIN, FAN_SPEED_LEVEL2);
		}
        else if(td.adc_temperature_c >= 35.00 && td.adc_temperature_c < 45.00)
		{
            fan_control(B_FAN_CONTROL_PIN, FAN_SPEED_LEVEL3);
		}
		else if(td.adc_temperature_c >= 45.00)
		{
            fan_control(B_FAN_CONTROL_PIN, FAN_SPEED_LEVEL4);
		}


		sleep_ms(2000);
    }

}
